package Java.view.game.zhajinhua;

import Java.utils.JDBC;
import Java.view.Common.GameFX;
import domain.User;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
import javafx.scene.control.Button;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.Duration;


import javax.lang.model.util.ElementScanner6;
import javax.swing.*;
import java.awt.*;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.concurrent.Semaphore;

public class zhajinhuaFX extends Application {
    private static final int WIDTH = 830;
    private static final int HEIGHT = 600;
    private Pane root;

    private ImageView backgroundView;
    private ImageView  ruleView;

    public PokerValue pokerValue=new PokerValue(this);
    public int allBet=0;//初始桌上的筹码 每轮开始每人必须拿出100
    public int round;//当前轮数 一共三轮
    int turn;//当前轮到0玩家 1电脑 3 玩家选择比牌
    int lastWinner;//上一轮赢家
    boolean roundIsOver=false;
    int huihe=0;//记录回合数

    User u;
    Player user=new Player();
    Player computer=new Player();

    private int minBet=100;

    //牌 无大小王
    private final ArrayList<Poker> pokerList = new ArrayList<>();


    private Button begin; //开始游戏
    private Button reset; //重新开始
    private Button back; //返回
    private Button giveUp;//弃牌
    private Button cmp;//比牌
    private Button noCmp;//不比牌
    private Button open;//看牌
    private Button bet;//跟注
    private Button addBet;//加注
    private TextField addBetNum;//加注值输入框

    //玩家名
    private Label playerName;
    private Label computerName;
    private Label playerBank;
    private Label computerBank;
    private Label showMinBet;
    private Label showAllBet;

    //卡牌位置
    private Point UserPoint=new Point(310,420);
    private Point computerPoint=new Point(310,70);
    private Point cardPoint=new Point(350,250);

    //操作提示
    private ImageView userDo;
    private ImageView computerDo;

public zhajinhuaFX(){}
    public zhajinhuaFX(User p){
        this.u=p;
       user.setName("玩家");
       computer.setName("电脑");
    }

    public void start(Stage primaryStage)  {
        primaryStage.setTitle("炸金花");
        primaryStage.getIcons().add(new Image("file:src/image/dizhu.png"));
        root = new Pane();
        //初始化组件
        initializeComponents();
        //设置主界面大小
        primaryStage.setScene(new Scene(root, WIDTH, HEIGHT));
        primaryStage.show();
    }


    private void initializeComponents() {
        //背景
        Image backgroundImg = new Image("file:src/image/背景2.jpg");
        backgroundView = new ImageView(backgroundImg);
        backgroundView.setFitWidth(WIDTH);
        backgroundView.setFitHeight(HEIGHT);
        root.getChildren().add(backgroundView);
        //规则
        Image ruleImg = new Image("file:src/image/炸金花规则.png");
        ruleView = new ImageView(ruleImg);
        ruleView.setFitWidth(WIDTH);
        ruleView.setFitHeight(HEIGHT);
        root.getChildren().add(ruleView);
        //开始按钮
        begin = createButton("file:src/image/game/开始游戏.png", 340, 470);
        begin.setOnAction(event -> {
            try {
                startGame();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        });
        //重置按钮
        reset = createButton("file:src/image/game/重新开始.png", 340, 470);
        reset.setVisible(false);//不可见
        reset.setOnAction(event -> {
            try {
                resetGame();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        });
        //返回按钮
        back = createButton("file:src/image/返回.png", 20, 20);
        back.setOnAction(event -> goBack());

        //看牌按钮
        open = createButton("file:src/image/game/看牌.png", 570, 420);
        open.setVisible(false);//不可见
        open.setOnAction(event -> openCard(user));
        //弃牌按钮
        giveUp = createButton("file:src/image/game/弃牌.png", 570, 480);
        giveUp.setVisible(false);//不可见
        giveUp.setOnAction(event -> win(computer));

        //比牌按钮
        cmp = createButton("file:src/image/game/比牌.png", 200,310);
        cmp.setVisible(false);//不可见
        cmp.setOnAction(event -> pk(user,computer));
        //不比按钮
        noCmp = createButton("file:src/image/game/不比.png", 470,310);
        noCmp.setVisible(false);//不可见
        noCmp.setOnAction(event ->doNoCmp(user));//不比 玩家操作结束 轮到电脑

        //跟注按钮
        bet = createButton("file:src/image/game/跟注.png", 200,310);
        bet.setVisible(false);//不可见
        bet.setOnAction(event -> doBet());
        //加注按钮
        addBet = createButton("file:src/image/game/加注.png", 580,310);
        addBet.setVisible(false);//不可见
        addBet.setOnAction(event -> doAddBet());
        //加注值输入框
        addBetNum = new TextField();
        addBetNum.setFont(Font.font("宋体", 16));
        addBetNum.setPromptText("请输入加注筹码");
        addBetNum.setPrefWidth(150);
        addBetNum.setPrefHeight(45);
        addBetNum.setLayoutX(430);
        addBetNum.setLayoutY(310);
        addBetNum.setVisible(false);

        //玩家名字标签
        playerName = new javafx.scene.control.Label(user.getName());
        playerName.setFont(javafx.scene.text.Font.font("黑体", 20));
        playerName.setTextFill(javafx.scene.paint.Color.BLACK);
        playerName.setLayoutX(550);
        playerName.setLayoutY(190);
        playerName.setVisible(false);//不可见
        //电脑名字标签
        computerName = new Label("电脑");
        computerName.setFont(Font.font("黑体", 20));
        computerName.setTextFill(Color.BLACK);
        computerName.setLayoutX(135);
        computerName.setLayoutY(190);
        computerName.setVisible(false);//不可见

        //玩家剩余金额展示
        playerBank = new Label(user.toString());
        playerBank.setFont(Font.font("黑体", 20));
        playerBank.setTextFill(Color.BLACK);
        playerBank.setLayoutX(135);
        playerBank.setLayoutY(380);
        playerBank.setVisible(false);//不可见
        //电脑剩余金额展示
        computerBank = new Label(computer.toString());
        computerBank.setFont(Font.font("黑体", 20));
        computerBank.setTextFill(Color.BLACK);
        computerBank.setLayoutX(135);
        computerBank.setLayoutY(190);
        computerBank.setVisible(false);//不可见

        showMinBet = new Label("当前底注："+minBet);
        showMinBet.setFont(Font.font("黑体", 20));
        showMinBet.setTextFill(Color.BLACK);
        showMinBet.setLayoutX(135);
        showMinBet.setLayoutY(255);
        showMinBet.setVisible(false);//不可见

        showAllBet=new  Label("筹码池："+allBet);
        showAllBet.setFont(Font.font("黑体", 20));
        showAllBet.setTextFill(Color.BLACK);
        showAllBet.setLayoutX(135);
        showAllBet.setLayoutY(275);
        showAllBet.setVisible(false);//不可见

        //用户操作标签
        userDo = new ImageView();
        userDo.setFitHeight(62);
        userDo.setFitWidth(120);
        userDo.setLayoutX(355);
        userDo.setLayoutY(250);
        userDo.toFront();

        //电脑操作标签
        computerDo = new ImageView();
        computerDo.setLayoutX(90);
        computerDo.setLayoutY(90);
        computerDo.setLayoutX(355);
        computerDo.setLayoutY(170);
        computerDo.toFront();

        //添加组件到主界面
        root.getChildren().addAll(begin,reset,back,
                open,cmp,noCmp,giveUp,bet,addBet,addBetNum,
                playerName,computerName,
                userDo,computerDo,
                playerBank,computerBank,showMinBet,showAllBet);
    }

    //开始游戏
    private void startGame() throws SQLException {
        // 移除规则介绍
        if (root != null && ruleView != null && backgroundView != null) {
            root.getChildren().remove(ruleView);
            backgroundView.setVisible(true);
        } else {
            System.out.println("组件未正确初始化！");
        }

        // 设置游戏初始状态
        round=0;
        begin.setVisible(false);
        //playerName.setVisible(true);
        //computerName.setVisible(true);
        playerBank.setVisible(true);
        computerBank.setVisible(true);
        showMinBet.setVisible(true);
        showAllBet.setVisible(true);

        // 启动一个后台线程处理游戏逻辑
        new Thread(() -> {
            try {
                // 三轮游戏
                while (round < 3) {
                    // 开始本轮游戏
                    Platform.runLater(() -> initCard());

                    user.isOpen=false;
                    roundIsOver = false; // 标记每轮是否结束
                    if (round == 1) {
                        turn = 0; // 第一轮玩家先开始
                    } else {
                        turn = lastWinner;
                    }

                    // 等待直到本轮结束
                    while (!roundIsOver) {
                        if (turn == 0) {
                            // 玩家操作
                            Platform.runLater(() -> {
                                // 操作按钮
                                //1 跟注 加注  看牌 弃牌
                                open.setVisible(!user.isOpen); // 随时可以看牌
                                giveUp.setVisible(true);
                                bet.setVisible(true);
                                addBet.setVisible(true);
                                addBetNum.setVisible(true);

                                cmp.setVisible(false);
                                noCmp.setVisible(false);
                            });
                        } else if(turn==1){ // 电脑操作
                            Platform.runLater(() -> {
                                cmp.setVisible(false);
                                noCmp.setVisible(false);
                                open.setVisible(false);
                                bet.setVisible(false);
                                addBet.setVisible(false);
                                addBetNum.setVisible(false);
                                aiPlay();
                            });
                        }else {//已下注 选择是否比牌
                            Platform.runLater(() -> {
                            cmp.setVisible(true);
                            noCmp.setVisible(true);

                            bet.setVisible(false);
                            addBet.setVisible(false);
                            addBetNum.setVisible(false);
                            });
                        }

                        // 给线程短暂休息，以便 UI 有时间更新
                        Thread.sleep(100);
                    }
                }

                // 三轮结束，游戏结束
                Platform.runLater(() -> {
                    try {
                        gameOver();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start(); // 启动线程
    }


    //跟注
    private void doBet() {

        if(user.bank>=minBet) {//筹码足够 可以继续游戏
            showDo(user,"跟注");
            allBet+=minBet;
            showAllBet.setText("筹码池:"+allBet);
            user.bank-=minBet;
            turn=1;//玩家操作结束 轮到电脑
            playerBank.setText(user.toString());
            user.isBet=true;
            turn=3;//下注成功 进行下一步操作
        }else {//筹码不够 玩家本轮失败
            win(computer);
        }
    }

    //加注
    private void doAddBet() {

        String betText = addBetNum.getText();
        addBetNum.setText("");//加注框清空

        try {
            int bet = Integer.parseInt(betText);
            if(bet<= user.bank){//可加注
                //有效加注
                if(bet>minBet){
                    showDo(user,"加注");
                    user.bank-=bet;//下注
                    minBet=bet;//更新最新底注
                    user.isBet=true;//记录下注情况
                    playerBank.setText(user.toString());
                    showMinBet.setText("当前底注："+minBet);
                    allBet+=bet;
                    showAllBet.setText("筹码池:"+allBet);
                    showDo(user,"加注");
                    turn=3;//下注成功 进行下一步操作

                }else {//加注失败
                    user.isBet=false;
                    System.out.println("加注失败"+minBet+","+bet);
                    //请输入有效加注值
                    Alert alert = new Alert(Alert.AlertType.INFORMATION);
                    alert.setTitle("提醒");
                    alert.setHeaderText("加注失败！");
                    alert.setContentText("请输入有效的加注筹码，数值应大于当前最低筹码"+minBet);

                    alert.showAndWait();
                }

            }else {//筹码不足 无法加注
                user.isBet=false;
                Alert alert = new Alert(Alert.AlertType.INFORMATION);
                alert.setTitle("提醒");
                alert.setHeaderText("加注失败！");
                alert.setContentText("您当前筹码为"+user.bank+"筹码不足，请重新下注");

                alert.showAndWait();

            }

        } catch (NumberFormatException e) {
            // 处理用户输入非数字的情况
            Alert alert = new Alert(Alert.AlertType.INFORMATION);
            alert.setTitle("提醒");
            alert.setHeaderText("输入不合法！");
            alert.setContentText("请输入有效的数字");

            alert.showAndWait();
        }

    }

    //比牌：本轮结束
    private void pk(Player first,Player second) {
        System.out.println("比牌");
    //展示双方的牌
        for (int i = 0; i < 3; i++) {
            user.handPoker.get(i).setImage(true);
            computer.handPoker.get(i).setImage(true);
        }

        int value1= pokerValue.judge(first.handPoker);
        int value2= pokerValue.judge(second.handPoker);
        if(value1>value2){
            win(first);
        }else {//平局则发起者败
            win(second);
        }
    }

    //不比牌：本轮继续
    private void doNoCmp(Player p){
        //轮到下一人
        if(p==user){
            showDo(user,"不比");
            turn=1;//轮到电脑
        }else {
            showDo(computer,"不比");
            turn=0;
        }
    }

    //本轮结束 p本轮赢家
    private void win(Player p){
        //获得筹码
        p.bank+=allBet;

        //记录本轮胜者 用于下一轮开始
        if(p==computer){
            lastWinner=1;
        }else lastWinner=0;

        //提示框提示当前轮结果
        int i=round+1;
        Alert alert = new Alert(Alert.AlertType.INFORMATION);
        alert.setTitle("第"+i+"轮结束");
        alert.setHeaderText("本轮胜者:"+p.getName()+"，赢得"+allBet);
        alert.setContentText(user.getName()+"当前筹码为"+user.bank+
                "，对手当前筹码为"+computer.bank);
        alert.showAndWait();


        allBet=0;//清空筹码
        minBet=100;
        showAllBet.setText("筹码池："+allBet);
        showMinBet.setText("当前底注："+minBet);

        //隐藏所有操作按钮
        open.setVisible(false);
        giveUp.setVisible(false);
        bet.setVisible(false);
        addBet.setVisible(false);
        addBetNum.setVisible(false);
        cmp.setVisible(false);
        noCmp.setVisible(false);

        //进入下一轮
        round++;
        roundIsOver=true;

    }


    private void showDo(Player p,String doWhat) {

    Image image=new Image("file:src/image/game/"+doWhat+"展示.png");

        // 根据玩家类型确定是 userDo 还是 computerDo
        ImageView currentDo = (p == user) ? userDo : computerDo;

        currentDo.setImage(image);
        currentDo.setVisible(true);
        // 创建一个时间轴，1秒后隐藏操作
        Timeline timeline = new Timeline(
                new KeyFrame(Duration.seconds(0.6), event -> currentDo.setVisible(false))
        );
        timeline.play(); // 播放时间轴

    }


    //看牌
    private void openCard(Player p) {
        minBet*=2;//最低筹码翻倍
        showMinBet.setText("当前底注"+minBet);
        p.isOpen=true;

        if(p.equals(user)){
            open.setVisible(false);//看牌按钮隐藏
            showDo(user,"看牌");
            //展示牌
            for (int i = 0; i < 3; i++) {
                user.handPoker.get(i).setImage(true);
                user.handPoker.get(i).setVisible(true);
            }
        }else showDo(computer,"看牌");

    }


    //重置游戏
    private void resetGame() throws SQLException {
        user.bank=10000;
        user.handPoker.clear();
        computer.bank=10000;
        computer.handPoker.clear();
        initializeComponents();
        startGame();
    }

    //返回按钮
    private void goBack() {
        new GameFX(u).start(new Stage());
        ((Stage) back.getScene().getWindow()).close();
    }


    private void gameOver() throws SQLException {
        //比较最终筹码
        int winner;
        if(user.bank>computer.bank){//玩家获胜
            winner=0;
        }else if(user.bank< computer.bank){
            winner=1;
        }else {
            winner=3;
        }

        Alert alert = new Alert(Alert.AlertType.INFORMATION);
        alert.setTitle("游戏结束");
        if(winner==0){
            alert.setHeaderText(u.getUsername()+"获胜");
            alert.setContentText("您最终筹码为"+user.bank+"，电脑最终筹码为"+computer.bank+
                    "，您获得了500欢乐豆");
            u.setHappyDou(u.getHappyDou()+500);


        }else if(winner==1){
            alert.setHeaderText("电脑获胜");
            alert.setContentText("您最终筹码为"+user.bank+"，电脑最终筹码为"+computer.bank+
                    "，您失去了500欢乐豆");
            u.setHappyDou(u.getHappyDou()-500);
        }else {
            alert.setHeaderText("平局");
        }
        alert.showAndWait();

        Connection connection= JDBC.getConnection();
        Statement statement=connection.createStatement();
        String sql1="UPDATE user SET happyDou ='"+u.getHappyDou()+"'WHERE username = '"+ u.getUsername() + "'";
        statement.executeUpdate(sql1);
    }

    private void aiPlay() {

//            if (huihe <= 4) {//三个来回之内
//                Platform.runLater(() -> {
//                //如果玩家看牌 我也看
//                if (user.isOpen) {
//                    aiPlayHasOpen();
//                } else {//没看牌 跟注 不比
                    aiPlayBet();
                    Timeline timeline = new Timeline(
                            new KeyFrame(Duration.seconds(0.5), event -> {
                                doNoCmp(computer);
                                huihe++;//记录回合数
                            })
                    );
                    timeline.play();

                    turn=0;

    }

    private void aiPlayHasOpen(){
        computer.isOpen=true;
        int value=pokerValue.judge(computer.handPoker);

        if(value>60000){
            //好牌 加注 pk
            aiPlayAddbet();
            Timeline timeline = new Timeline(
                    new KeyFrame(Duration.seconds(0.5), event -> {
                        pk(computer,user);
                    })
            );
            timeline.play();

        }else if(value>40000&&
                value<=60000){
            // 加注 不比
            aiPlayAddbet();
            Timeline timeline = new Timeline(
                    new KeyFrame(Duration.seconds(0.5), event -> {
                        doNoCmp(computer);
                        huihe++;
                    })
            );
            timeline.play();
        }else if(value>20000&&
                value<=40000){
            //跟注 不比
            aiPlayBet();
            Timeline timeline = new Timeline(
                    new KeyFrame(Duration.seconds(0.5), event -> {
                        doNoCmp(computer);
                        huihe++;
                    })
            );
            timeline.play();
        }
        else {//牌太臭 弃牌
            win(user);
        }
    }

    private void aiPlayBet(){
        showDo(computer,"跟注");
        System.out.println("电脑跟注"+minBet);
        computer.bank-=minBet;
        allBet+=minBet;
        showAllBet.setText("筹码池:"+allBet);
        computerBank.setText(computer.toString());
    }
    private void aiPlayAddbet(){
        showDo(computer,"加注");
        minBet+=200;
        computer.bank-=minBet;
        allBet+=200;
        showAllBet.setText("筹码池:"+allBet);
    }



    private void initCard(){//洗牌发牌
        Poker.Score[] scores = {Poker.Score._2, Poker.Score._3,
                Poker.Score._4, Poker.Score._5, Poker.Score._6, Poker.Score._7, Poker.Score._8,
                Poker.Score._9, Poker.Score._10, Poker.Score.J, Poker.Score.Q, Poker.Score.K, Poker.Score.A};
        Poker.Suit[] suits = {Poker.Suit.SPADE, Poker.Suit.CLUB, Poker.Suit.DIAMOND, Poker.Suit.HEART};


        for (int i = 0; i < 13; i++) {
            for (int j = 0; j < 4; j++) {
                Poker p = new Poker(this,suits[j], scores[i]);
                p.setTranslateX(357);
                p.setTranslateY(15);
                pokerList.add(p);//将生成的牌加入牌盒
                root.getChildren().add(p);
                p.setImage(false);//设置牌面为背面
                p.setVisible(false);

            }
        }
        Collections.shuffle(pokerList);//洗牌
        for (int i = 0; i <6; i+=2) {
            Poker p1=pokerList.get(i);
            Poker p2=pokerList.get(i+1);
            p1.setVisible(true);
            p2.setVisible(true);
            p1.setImage(false);
            p2.setImage(false);
            user.handPoker.add(p1);
            computer.handPoker.add(p2);

            //动画效果
            move(p1,cardPoint, new Point(UserPoint.x+30*i, UserPoint.y));
            move(p2,cardPoint, new Point(computerPoint.x+30*i, computerPoint.y));
            p1.toFront();
            p2.toFront();
        }
    }

    public static void move(Poker poker, Point from, Point to) {
        // 创建TranslateTransition动画对象
        TranslateTransition transition = new TranslateTransition(Duration.millis(500),poker );
        // 设置动画的起始位置
        transition.setFromX(from.x);
        transition.setFromY(from.y);
        // 设置动画的结束位置
        transition.setToX(to.x);
        transition.setToY(to.y);
        // 启动动画
        transition.play();
    }

    private Button createButton(String imagePath, int x, int y) {
        Button button = new Button();
        Image image = new Image(imagePath);
        ImageView imageView = new ImageView(image);
        button.setGraphic(imageView);
        button.setLayoutX(x);
        button.setLayoutY(y);
        button.setStyle("-fx-background-color: transparent; -fx-border-width: 0;");
        return button;
    }

}
